{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 机器学习练习 2 - 逻辑回归"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这个笔记包含了以Python为编程语言的Coursera上机器学习的第二次编程练习。请参考 [作业文件](ex2.pdf) 详细描述和方程。\n",
    "在这一次练习中，我们将要实现逻辑回归并且应用到一个分类任务。我们还将通过将正则化加入训练算法，来提高算法的鲁棒性，并用更复杂的情形来测试它。\n",
    "\n",
    "代码修改并注释：黄海广，haiguang2000@qq.com"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 逻辑回归"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在训练的初始阶段，我们将要构建一个逻辑回归模型来预测，某个学生是否被大学录取。设想你是大学相关部分的管理者，想通过申请学生两次测试的评分，来决定他们是否被录取。现在你拥有之前申请学生的可以用于训练逻辑回归的训练样本集。对于每一个训练样本，你有他们两次测试的评分和最后是被录取的结果。为了完成这个预测任务，我们准备构建一个可以基于两次测试评分来评估录取可能性的分类模型。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们从检查数据开始。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Exam 1</th>\n",
       "      <th>Exam 2</th>\n",
       "      <th>Admitted</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>34.623660</td>\n",
       "      <td>78.024693</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>30.286711</td>\n",
       "      <td>43.894998</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>35.847409</td>\n",
       "      <td>72.902198</td>\n",
       "      <td>0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>60.182599</td>\n",
       "      <td>86.308552</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>79.032736</td>\n",
       "      <td>75.344376</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      Exam 1     Exam 2  Admitted\n",
       "0  34.623660  78.024693         0\n",
       "1  30.286711  43.894998         0\n",
       "2  35.847409  72.902198         0\n",
       "3  60.182599  86.308552         1\n",
       "4  79.032736  75.344376         1"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "path = 'ex2data1.txt'\n",
    "data = pd.read_csv(path, header=None, names=['Exam 1', 'Exam 2', 'Admitted'])\n",
    "data.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们创建两个分数的散点图，并使用颜色编码来可视化，如果样本是正的（被接纳）或负的（未被接纳）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAtcAAAHjCAYAAADojTN7AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3X943XV9///HM/yqJJkIdnyhrCuj0YkIdYtMtFKggqwq\nhOoI6rS6zrp9UPtDZ8u16/LXtQmiH2vUbX5YGeLGahhLA9fs/FVxWnS4VKsgxaW6grXlhyDzJP6C\n5vn943XezUl6TnJyzvuc96/77bp6nZz3OUleeSdNHu/Xeb6eL3N3AQAAAGheR9IDAAAAAPKCcA0A\nAADEhHANAAAAxIRwDQAAAMSEcA0AAADEhHANAAAAxIRwDQAAAMSEcA0AAADEhHANAAAAxOTopAfQ\njGc+85m+aNGipIcBAACAnNu1a9dP3H3+bM/LdLhetGiRRkZGkh4GAAAAcs7MHqjneZSFAAAAADEh\nXAMAAAAxIVwDAAAAMcl0zTUAAEBWPfnkk9q/f79++ctfJj0UVJg3b55OO+00HXPMMQ29P+EaAAAg\nAfv371d3d7cWLVokM0t6OJDk7nrssce0f/9+nX766Q19DMpCAAAAEvDLX/5SJ510EsE6RcxMJ510\nUlOvJhCuAQAAEkKwTp9mvyeEawAAACAmhGsAAIAMKJWkLVukjRvDbakU38ceHh6Wmen++++v+vgb\n3/hG3XbbbXV/vAMHDujVr361JGn37t3avn374ce+8pWv6Otf//qcx7ho0SL95Cc/mfP7tRvhGgAA\nIOV27pQWLJDWrZOuvz7cLlgQjsdh69atWrp0qbZu3RrLxzv11FMPh/G4wnVWEK4BAABSrFSSVqwI\nt+Pj4dj4+OTxsbHmPv7Y2Jh27typG2+8UZ/5zGckha4Zb33rW/XsZz9bL33pS/XII48cfv6iRYt0\nzTXXaMmSJert7dW3vvUtvexlL9MZZ5yhT37yk5Kkffv26ayzztKvf/1rvfvd79bg4KCWLFmiD37w\ng/rkJz+pzZs3a8mSJfra176mRx99VK961av0ghe8QC94wQt01113SZIee+wxXXLJJXruc5+rP/3T\nP5W7N/eFtknLWvGZ2T9IeoWkR9z9rPKxEyUNSlokaZ+kK939p+XHrpG0WtIhSW9398+3amwAAABZ\nMTgoTUxUf2xiIjy+enXjH//222/XpZdeqmc961k66aSTtGvXLj3wwAP6/ve/r/vuu08PP/ywzjzz\nTP3Jn/zJ4fdZuHChdu/erfXr1+uNb3yj7rrrLv3yl7/UWWedpT/7sz87/Lxjjz1W73//+zUyMqJP\nfOITkqRf/OIX6urq0jvf+U5J0mtf+1qtX79eS5cu1YMPPqiXvexl2rNnj973vvdp6dKleve7363P\nfvazuvHGGxv/ItuolX2uPyXpE5I+XXFsk6Qd7n6dmW0q399oZmdKukrScyWdKulLZvYsdz/UwvEB\nAACk3ujo5Iz1dOPj0t69zX38rVu3au3atZKkq666Slu3btVTTz2l17zmNTrqqKN06qmn6qKLLpry\nPpdddpkk6XnPe57GxsbU3d2t7u5uHXfccXriiSfm9Pm/9KUv6b777jt8/2c/+5nGxsb01a9+VUND\nQ5Kkl7/85XrGM57RzJfZNi0L1+7+VTNbNO3w5ZIuKL99s6SvSNpYPv4Zd/+VpP8xs72SzpX0jVaN\nDwAAIAt6eqTOzuoBu7NTWry48Y/9+OOP68tf/rLuuecemZkOHTokM9MVV1wx4/sdd9xxkqSOjo7D\nb0f3n3rqqTmNYWJiQv/5n/+pefPmzf0LSKF211yf7O4Hy28/JOnk8tsLJP2o4nn7y8eOYGZrzGzE\nzEYeffTR1o0UAAAgBfr7pY4aia2jIzzeqNtuu02vf/3r9cADD2jfvn360Y9+pNNPP10nnXSSBgcH\ndejQIR08eFB33nlnw5+ju7tbpYrWJtPvX3LJJfr4xz9++P7u3bslSeeff77++Z//WZL07//+7/rp\nT3/a8BjaKbEFjR6q0udcme7uN7h7r7v3zp8/vwUjAwAASI/ubmn79nDb2RmOdXZOHu/qavxjb926\n9YhZ6le96lU6ePCgenp6dOaZZ+oNb3iDzjvvvIY/x4UXXqj77rtPS5Ys0eDgoF75yldq27Zthxc0\nfuxjH9PIyIjOPvtsnXnmmYcXRb7nPe/RV7/6VT33uc/V0NCQFi5c2PgX2kbWypWX5bKQf6tY0Ph9\nSRe4+0EzO0XSV9z92eXFjHL3a8vP+7yk97r7jGUhvb29PjIy0rLxp5q7NDws9fVJlTsJ1ToOAABS\nZc+ePXrOc55T9/PHxsLixb17QylIf39zwRq1VfvemNkud++d7X3bPXN9h6RV5bdXSbq94vhVZnac\nmZ0uqUfSN9s8tmwZHpZWrpTWrw+BWgq369eH48PDyY4PAADEqqsrdAW59tpwS7BOp1a24tuqsHjx\n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\ncC1JkiT15BuusxrFcxyTBwAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x98b9dd8>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "positive = data[data['Admitted'].isin([1])]\n",
    "negative = data[data['Admitted'].isin([0])]\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(12,8))\n",
    "ax.scatter(positive['Exam 1'], positive['Exam 2'], s=50, c='b', marker='o', label='Admitted')\n",
    "ax.scatter(negative['Exam 1'], negative['Exam 2'], s=50, c='r', marker='x', label='Not Admitted')\n",
    "ax.legend()\n",
    "ax.set_xlabel('Exam 1 Score')\n",
    "ax.set_ylabel('Exam 2 Score')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "看起来在两类间，有一个清晰的决策边界。现在我们需要实现逻辑回归，那样就可以训练一个模型来预测结果。方程实现在下面的代码示例在\"exercises\" 文件夹的 \"ex2.pdf\" 中。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# sigmoid 函数\n",
    "g 代表一个常用的逻辑函数（logistic function）为S形函数（Sigmoid function），公式为： \\\\[g\\left( z \\right)=\\frac{1}{1+{{e}^{-z}}}\\\\] \n",
    "合起来，我们得到逻辑回归模型的假设函数： \n",
    "\t\\\\[{{h}_{\\theta }}\\left( x \\right)=\\frac{1}{1+{{e}^{-{{\\theta }^{T}}X}}}\\\\] "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def sigmoid(z):\n",
    "    return 1 / (1 + np.exp(-z))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们做一个快速的检查，来确保它可以工作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\nK7EYS1JveeklmDIFxoyBPn1yp5EkrcRiLEm95eqri63aHKOQpJpkMZak3pASXHwx7LQTvOtdudNI\nkjrRN3cASWoK110Hd90FP/85ROROI0nqhCvGklRtra1wxhnFavFJJ+VOI0nqgivGklRtl1wC06bB\nVVdBv36500iSuuCKsSRV08KF8LWvwV57wdFH504jSVoNV4wlqZrOOw/mzCn2L3a2WJJqmivGklQt\nL74I55wDhx0G731v7jSSpG5YjCWpWs4+G+bPh+98J3cSSVIZLMaSVA1PPgnnnw///u+w666500iS\nymAxlqRqOOssWGcd+MY3cieRJJXJYixJlfbAA3DppfD5z8OQIbnTSJLKZDGWpEo7/XTYdNPioySp\nbrhdmyRV0i23wO9/D9//Pmy2We40kqQ14IqxJFVKWxucemoxPnHKKbnTSJLWkCvGklQpV14J994L\nv/41rLde7jSSpDXkirEkVcLixXDmmbDbbnDCCbnTSJLWgivGklQJF14IM2bA734HffrkTiNJWguu\nGEtST82fD9/8Juy/P4walTuNJGktWYwlqad+8AOYOxe++12IyJ1GkrSWLMaS1BPPPgs//CEceyyM\nGJE7jSSpByzGktQT3/wmLFoE3/527iSSpB6yGEvS2nr88eJNdyefDDvumDuNJKmHLMaStLbOPLPY\nr/irX82dRJJUARZjSVobd98NV10FX/oSDBqUO40kqQIsxpK0plKC006DLbaAL34xdxpJUoWUVYwj\nYmREPBYR0yPi9E6e/0hEPBgRD0XEnRGxe+WjSlKNmDIFbrutGKHYaKPcaSRJFdJtMY6IPsAFwCjg\nbcDYiHjbSof9E3hfSmk34FvAhZUOKkk1YenSYrV4hx2KN91JkhpGOZeEHgFMTynNBIiI8cCRwLRl\nB6SU7uxw/F3ANpUMKUk149JL4eGH4fLLoV+/3GkkSRVUzijFYGBWh89ntz/WlZOAKZ09EREnR8TU\niJg6d+7c8lNKUi144w046yzYc8/igh6SpIZSzopx2SLiAIpivG9nz6eULqR9zGL48OGpkl9bkqru\n/PNh1iy45BIv/SxJDaicYjwHGNLh823aH1tBRLwD+BUwKqX0YmXiSVKNePllOPtsGDUKDjggdxpJ\nUhWUM0pxD7BjRGwbEf2BMcCkjgdExFBgAnBiSunxyseUpMzOOQdeeaX4KElqSN2uGKeUWiPiFOAG\n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\nD/iWfPodA7wwAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x9a9af60>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "nums = np.arange(-10, 10, step=1)\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(12,8))\n",
    "ax.plot(nums, sigmoid(nums), 'r')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "棒极了！现在，我们需要编写代价函数来评估结果。\n",
    "代价函数：\n",
    "$J\\left( \\theta  \\right)=\\frac{1}{m}\\sum\\limits_{i=1}^{m}{[-{{y}^{(i)}}\\log \\left( {{h}_{\\theta }}\\left( {{x}^{(i)}} \\right) \\right)-\\left( 1-{{y}^{(i)}} \\right)\\log \\left( 1-{{h}_{\\theta }}\\left( {{x}^{(i)}} \\right) \\right)]}$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def cost(theta, X, y):\n",
    "    theta = np.matrix(theta)\n",
    "    X = np.matrix(X)\n",
    "    y = np.matrix(y)\n",
    "    first = np.multiply(-y, np.log(sigmoid(X * theta.T)))\n",
    "    second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))\n",
    "    return np.sum(first - second) / (len(X))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在，我们要做一些设置，和我们在练习1在线性回归的练习很相似。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# add a ones column - this makes the matrix multiplication work out easier\n",
    "data.insert(0, 'Ones', 1)\n",
    "\n",
    "# set X (training data) and y (target variable)\n",
    "cols = data.shape[1]\n",
    "X = data.iloc[:,0:cols-1]\n",
    "y = data.iloc[:,cols-1:cols]\n",
    "\n",
    "# convert to numpy arrays and initalize the parameter array theta\n",
    "X = np.array(X.values)\n",
    "y = np.array(y.values)\n",
    "theta = np.zeros(3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们来检查矩阵的维度来确保一切良好。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.,  0.,  0.])"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "theta"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "((100, 3), (3,), (100, 1))"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X.shape, theta.shape, y.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们计算初始化参数的代价函数(theta为0)。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.69314718055994529"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cost(theta, X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "看起来不错，接下来，我们需要一个函数来计算我们的训练数据、标签和一些参数thata的梯度。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# gradient descent(梯度下降)\n",
    "* 这是批量梯度下降（batch gradient descent）  \n",
    "* 转化为向量化计算： $\\frac{1}{m} X^T( Sigmoid(X\\theta) - y )$\n",
    "$$\\frac{\\partial J\\left( \\theta  \\right)}{\\partial {{\\theta }_{j}}}=\\frac{1}{m}\\sum\\limits_{i=1}^{m}{({{h}_{\\theta }}\\left( {{x}^{(i)}} \\right)-{{y}^{(i)}})x_{_{j}}^{(i)}}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def gradient(theta, X, y):\n",
    "    theta = np.matrix(theta)\n",
    "    X = np.matrix(X)\n",
    "    y = np.matrix(y)\n",
    "    \n",
    "    parameters = int(theta.ravel().shape[1])\n",
    "    grad = np.zeros(parameters)\n",
    "    \n",
    "    error = sigmoid(X * theta.T) - y\n",
    "    \n",
    "    for i in range(parameters):\n",
    "        term = np.multiply(error, X[:,i])\n",
    "        grad[i] = np.sum(term) / len(X)\n",
    "    \n",
    "    return grad"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "注意，我们实际上没有在这个函数中执行梯度下降，我们仅仅在计算一个梯度步长。在练习中，一个称为“fminunc”的Octave函数是用来优化函数来计算成本和梯度参数。由于我们使用Python，我们可以用SciPy的“optimize”命名空间来做同样的事情。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们看看用我们的数据和初始参数为0的梯度下降法的结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ -0.1       , -12.00921659, -11.26284221])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gradient(theta, X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在可以用SciPy's truncated newton（TNC）实现寻找最优参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 23,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([-25.1613186 ,   0.20623159,   0.20147149]), 36, 0)"
      ]
     },
     "execution_count": 23,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import scipy.optimize as opt\n",
    "result = opt.fmin_tnc(func=cost, x0=theta, fprime=gradient, args=(X, y))\n",
    "result"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们看看在这个结论下代价函数计算结果是什么个样子~"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.20349770158947464"
      ]
     },
     "execution_count": 24,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "cost(result[0], X, y)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "接下来，我们需要编写一个函数，用我们所学的参数theta来为数据集X输出预测。然后，我们可以使用这个函数来给我们的分类器的训练精度打分。\n",
    "逻辑回归模型的假设函数： \n",
    "\t\\\\[{{h}_{\\theta }}\\left( x \\right)=\\frac{1}{1+{{e}^{-{{\\theta }^{T}}X}}}\\\\] \n",
    "当${{h}_{\\theta }}$大于等于0.5时，预测 y=1\n",
    "\n",
    "当${{h}_{\\theta }}$小于0.5时，预测 y=0 。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def predict(theta, X):\n",
    "    probability = sigmoid(X * theta.T)\n",
    "    return [1 if x >= 0.5 else 0 for x in probability]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 26,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy = 89%\n"
     ]
    }
   ],
   "source": [
    "theta_min = np.matrix(result[0])\n",
    "predictions = predict(theta_min, X)\n",
    "correct = [1 if ((a == 1 and b == 1) or (a == 0 and b == 0)) else 0 for (a, b) in zip(predictions, y)]\n",
    "accuracy = (sum(map(int, correct)) % len(correct))\n",
    "print ('accuracy = {0}%'.format(accuracy))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "我们的逻辑回归分类器预测正确，如果一个学生被录取或没有录取，达到89%的精确度。不坏！记住，这是训练集的准确性。我们没有保持住了设置或使用交叉验证得到的真实逼近，所以这个数字有可能高于其真实值（这个话题将在以后说明）。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 正则化逻辑回归"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "在训练的第二部分，我们将要通过加入正则项提升逻辑回归算法。如果你对正则化有点眼生，或者喜欢这一节的方程的背景，请参考在\"exercises\"文件夹中的\"ex2.pdf\"。简而言之，正则化是成本函数中的一个术语，它使算法更倾向于“更简单”的模型（在这种情况下，模型将更小的系数）。这个理论助于减少过拟合，提高模型的泛化能力。这样，我们开始吧。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "设想你是工厂的生产主管，你有一些芯片在两次测试中的测试结果。对于这两次测试，你想决定是否芯片要被接受或抛弃。为了帮助你做出艰难的决定，你拥有过去芯片的测试数据集，从其中你可以构建一个逻辑回归模型。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "和第一部分很像，从数据可视化开始吧！"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 27,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Test 1</th>\n",
       "      <th>Test 2</th>\n",
       "      <th>Accepted</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0.051267</td>\n",
       "      <td>0.69956</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>-0.092742</td>\n",
       "      <td>0.68494</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>-0.213710</td>\n",
       "      <td>0.69225</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>-0.375000</td>\n",
       "      <td>0.50219</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>-0.513250</td>\n",
       "      <td>0.46564</td>\n",
       "      <td>1</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "     Test 1   Test 2  Accepted\n",
       "0  0.051267  0.69956         1\n",
       "1 -0.092742  0.68494         1\n",
       "2 -0.213710  0.69225         1\n",
       "3 -0.375000  0.50219         1\n",
       "4 -0.513250  0.46564         1"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "path =  'ex2data2.txt'\n",
    "data2 = pd.read_csv(path, header=None, names=['Test 1', 'Test 2', 'Accepted'])\n",
    "data2.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAuMAAAHjCAYAAACJlRE5AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3X14pHV59//PGcAbycYHHkTIQqG/3SpaYVkjFd2a4iOs\nD2S3YEBFb92j+Fh32V/bXWt7a6s9aNfWNLa03HRF0Vtha5sE2q6KqL0xUh+y/EAQkCy6KLs8CaiT\nUFsx5++P71ybK5OZZJKZuR7fr+PIMZnrmkm+c2Uyc873Or/nae4uAAAAAMnrSnsAAAAAQFkRjAMA\nAAApIRgHAAAAUkIwDgAAAKSEYBwAAABICcE4AAAAkBKCcQAAACAlBOMAAABASgjGAQAAgJQcmvYA\nknT00Uf7SSedlPYwAAAAUHB79uz5sbsfs9jtShWMn3TSSZqYmEh7GAAAACg4M7u3mduRpgIAAACk\nhGAcAAAASAnBOAAAAJCSUuWMAwAAIPjFL36h++67Tz//+c/THkquHX744Vq5cqUOO+ywZd2fYBwA\nAKCE7rvvPvX09Oikk06SmaU9nFxydz3yyCO67777dPLJJy/rZ5CmAgAAUEI///nPddRRRxGIt8DM\ndNRRR7V0doFgHAAAoKQIxFvX6jEkGAcAAABSQjAOAACARVUq0s6d0rZt4bJSac/PHRsbk5nprrvu\nas8PXMRf//Vf6/HHH1/Sff793/9dr3nNazoyHoJxAAAALGh8XOrtlbZskXbsCJe9vWF7q66++mqt\nW7dOV199des/rAnLCcY7iWAcAAAADVUq0vr14XJ6Omybnp7dPjW1/J89NTWl8fFxffzjH9c111xz\ncPtf/MVf6HnPe55OO+00bd++XZK0d+9evfzlL9dpp52mtWvX6p577pEkfeQjH9ELXvACnXrqqfrA\nBz4gSdq3b5+e/exn641vfKNOOeUUnXfeeXr88cf1sY99TAcOHNBZZ52ls846S5J0/fXX68wzz9Ta\ntWt1/vnna6r6gL7whS/o2c9+ttauXauRkZHlP8hFEIwDAACgoV27pJmZ+vtmZsL+5br22mt19tln\n69d+7dd01FFHac+ePfr85z+va6+9Vt/85jd166236g/+4A8kSW984xv17ne/W7feeqtuuukmHXfc\ncbr++us1OTmpb33rW7rlllu0Z88e3XjjjZKk733ve3rXu96lO++8U095ylP0d3/3d3rve9+r448/\nXl/96lf11a9+VT/+8Y/14Q9/WDfccINuvvlm9fX16aMf/ah+/vOf63d+53f0L//yL9qzZ48eeOCB\n5T/IRRCMAwAAoKHJydkZ8VrT09Levcv/2VdffbUuuOACSdIFF1ygq6++WjfccIPe+ta36ogjjpAk\nHXnkkapUKtq/f782bNggKTTaOeKII3T99dfr+uuv1+mnn661a9fqrrvu0uTkpCTphBNO0Itf/GJJ\n0pve9CaN18mp+cY3vqE77rhDL37xi7VmzRpdddVVuvfee3XXXXfp5JNP1urVq2VmetOb3rT8B7kI\nmv4AAACgodWrpe7u+gF5d7e0atXyfu6jjz6qr3zlK7rttttkZvrlL38pM9P555/f9M9wd73vfe/T\n29/+9jnb9+3bN6/kYL0ShO6uV7ziFfPy1W+55ZYlPJLWMDMOAACAhgYHpa4GEWNXV9i/HP/0T/+k\niy66SPfee6/27dunH/3oRzr55JP11Kc+VZ/4xCcOLrJ89NFH1dPTo5UrV2psbEyS9F//9V96/PHH\n9apXvUpXXnnlwTzv/fv366GHHpIk/fCHP9R//Md/SJI++9nPat26dZKknp4eVaqlYF74whfq61//\nuvZWp/enp6d1991369nPfrb27dt3MC+9k4tLCcYBAADQUE+PtHt3uOzuDtu6u2e3r1ixvJ979dVX\nH0w7ifz2b/+27r//fr3uda9TX1+f1qxZo7/8y7+UJH3605/Wxz72MZ166ql60YtepAceeECvfOUr\n9YY3vEFnnnmmnve85+m88847GGg/61nP0mWXXaZTTjlFjz32mN75zndKki6++GKdffbZOuuss3TM\nMcfok5/8pC688EKdeuqpOvPMM3XXXXfp8MMP1xVXXKFXv/rVWrt2rZ7xjGcs70E2wdy9Yz88a/r6\n+nxiYiLtYQAAAKTuzjvv1CmnnNL07aemwmLNvXtDasrg4PID8U7bt2+fXvOa1+j2229P5PfVO5Zm\ntsfd+xa7LznjAFDLXRobkwYGpHiOYaPtAFACK1ZImzalPYriIU0FAGqNjUkbN0qXXBICcClcXnJJ\n2F7NWQQAZNNJJ52U2Kx4q5gZB4BaAwPS5s3S8HC4PjQUAvHh4bB9YCDd8QEACoNgHABqmYUAXAoB\neBSUb94ctpOiAgBoE9JUAKCeeEAeIRDPL3dpdHQ27Wix7QCQEIJxAKgnyhGPi+eQI19YBwAgowjG\nAaBWFKRFOeIzM7M55ATk+RRfBxD9DVkHADSng2eWDjnkEK1Zs0a//uu/rte+9rX6yU9+suh9XvSi\nFy3rd42NjemOO+5Y8v1WdLh+I8E4ANQaG5sN0qLUlKGh2WCOWdT8qf0bdnXN/xsDqK+DZ5ae/OQn\n65ZbbtHtt9+uI488Updddtmi97npppuW9buWG4x3GsE4ANQaGJBGRuYGaVEwNzLCLGpesQ4AWJ6E\nziydeeaZ2r9//8HrH/nIR/SCF7xAp556qj7wgQ8c3B6fqW50m0996lM69dRTddppp+miiy7STTfd\npOuuu06///u/rzVr1uiee+7RPffco7PPPlvPf/7z9Zu/+Zu66667JEk/+MEPDnb0/KM/+qO2PLaF\nUE0FAGqZSTUtmhfcjnxotA6AgBxYWAIVpn75y1/qy1/+sjZVuwpdf/31mpyc1Le+9S25u173utfp\nxhtv1Ete8pKD92l0m6OOOkof/vCHddNNN+noo4/Wo48+qiOPPFKve93r9JrXvEbnnXeeJOllL3uZ\nLr/8cq1evVrf/OY39a53vUtf+cpXtHnzZr3zne/Um9/85qZm6lvFzDgAoPhYBwC0pkNnlv7zP/9T\na9as0TOf+Uw9+OCDesUrXiEpBNrXX3+9Tj/9dK1du1Z33XWXJicn59y30W2+8pWv6Pzzz9fRRx8t\nSTryyCPn/d6pqSnddNNNOv/887VmzRq9/e1v1/333y9J+vrXv64LL7xQknTRRRe19Piawcw4AKD4\nGq0DkML2/n7OegAL6dCZpShn/PHHH9erXvUqXXbZZXrve98rd9f73vc+vf3tb19gSPVv8zd/8zeL\n/t6ZmRk97WlP0y233FJ3vyV4toyZcQBA8bEOAFi+BM4sHXHEEfrYxz6mv/qrv9ITTzyhV73qVbry\nyis1NTUlSdq/f78eeuihOfdpdJuXvvSl+tznPqdHHnlEkvToo49Kknp6elSpVCRJT3nKU3TyySfr\nc5/7XPUhum699VZJ0otf/GJdc801kqTPfOYzLT+2xRCMAwCKL8r3r53tarQdwKyEKkydfvrpOvXU\nU3X11Vfrla98pd7whjccXEh53nnnHQyko1nrRrd57nOfq/e///3q7+/Xaaedpq1bt0qSLrjgAn3k\nIx/R6aefrnvuuUef+cxn9PGPf1ynnXaanvvc5+raa6+VJA0PD+uyyy7T8573vDkLSjvFvER5cn19\nfT4xMZH2MAAAAFJ355136pRTTln8hu4h4B4YmPvBtdH2DnrkkUe0du1a3XvvvYn8vmbVO5Zmtsfd\n+xa7LzPjAAAAaCwjZ5YOHDigM888U7/3e7+XyO9LCgs4AQAAkHnHH3+87r777rSH0XbMjAMAAJRU\nmdKVO6XVY0gwDgAAUEKHH364HnnkEQLyFri7HnnkER1++OHL/hmkqQAAAJTQypUrdd999+nhhx9O\neyi5dvjhh2vlypXLvj/BOAAAQAkddthhOvnkk9MeRumRpgIAAACkhGAcqMddGh2d31Ws0XZgKXh+\nAQCqUg3GzexKM3vIzG5vsN/M7GNmttfMvmNma2P7zjaz71X3bU9u1CiFsTFp48a5bX6jdsAbN7at\n2xhKiucXAKAq7ZnxT0o6e4H950haXf26WNLfS5KZHSLpsur+50i60Mye09GRolwGBmbb/EYB0yWX\nzLYDHhhIe4RoRdoz0zy/AABVqQbj7n6jpEcXuMm5kj7lwTckPc3MjpN0hqS97v59d/9vSddUbwu0\nh5k0NDQbMHV1zQZKQ0OJdRtDh6Q9M83zCwBQlfbM+GJ6Jf0odv2+6rZG2+cxs4vNbMLMJijdgyWJ\nAqY4AqViyMLMNM8vAICyH4y3zN2vcPc+d+875phj0h4O8iQK0OLiM6nIryzMTPP8AgAo+8H4fkkn\nxK6vrG5rtB1oj9qZ0pmZ+TOpyLc0Z6Z5fgEAqrIejF8n6c3VqiovlPRTd79f0rclrTazk83sSZIu\nqN4WaI+xsfkzpfGZVKpd5F+aM9M8vwAAVal24DSzqyX9lqSjzew+SR+QdJgkufvlknZLWi9pr6TH\nJb21uu8JM3uPpC9KOkTSle7+3cQfAIprYEAaGQmX0UxpFDD195e62kWlIu3aJU1OSqtXS4ODUk9P\n2qNaotqZ6aGh2etS52fIeX4BAKrMS3Q6tK+vzycmJtIeBpBb4+PS+vUhq2J6WuruDunWu3dL69al\nPbolGB0NVVPiM9PxAH1kRNqwIe1RAgByzMz2uHvforcjGAfQjEpF6u0Nl7V6eqQDB6QVK5If17K4\nh1SQ+Mz0QtsBAFiiZoPxrOeMA8iIXbvCjHg9MzNhf26YhZnv2oC70XYAADqEYBxAUyYnQ2pKPdPT\n0t69yY4HAIAiIBgH0JTVq0OOeD3d3dKqVcmOBwCAIiAYB9CUwcGwWLOerq6wH6jLPSyarV2j1Gg7\nAJQIwTiApvT0hKopPT2zM+Td3bPbc7N4E8kbGwvVa+J13KPqNRs3UlcdQKmlWmccQL6sWxeqpuza\nFXLEV60KM+IE4ljQwMBsQyNpbl33zZupqw6g1ChtCGQV5ffQrDw8V+J13CPxOu8AUDCUNgTyjlP7\naFYenitRh9E4AnEAIBgHMit+aj8Ksji1j3ry8FyJxhQX//AAACVFMI5yykN1h2gmMQqyurpmgytm\nFBGX9edK7YeDmZn5Hx4AoKTIGUc5jY6G0/fxYCUeMIyMhE6MWeA+t6bgzEz6wRWyKavPlTz9vwFA\nm5AzDiwkD6f1JU7to3lZfq4MDISAOz5LH83mj4xk5/8NAFJAMI5yyvppfYlT+2he1p8rZmHmu/b/\nqtF2IC4PaYVACwjGUV5Zr+4wNjb/A0L8A0QWKmQgG3iuoMjyUC0IaAHBOMory6f1JU7to3k8V1Bk\neUkrBJaJBZwop9oX89qOgFmaIQeAsqNpFHKo2QWcBOMoJ6o7AEC+ZLVaENAA1VSAhXBaHwDyI+tp\nhUALCMZRTlR3AIB8yHq1IKBFh6Y9AAAAgIYaVQuSwvb+ftIKkWsE4wAAILuitMKBgflphf39pBUi\n9wjGAQBAdkXpg81uB3KGnHEAAAAgJQTjAAAAQEoIxgEAAICUEIwDAAAAKSEYBwAgSe6hC3BtfexG\n2wEUGsE4ALRBpSLt3Clt2xYuK5W0R4TMGhuTNm6c27AmamyzcWPYD6A0KG0IAC0aH5fWrw+NAaen\npe5uaetWafduad26tEeHzBkYmO0gKYV62fEOk9TNBkrFvESnw/r6+nxiYiLtYQAokEpF6u2tPxPe\n0yMdOCCtWJH8uJBx8RbvkXiHSQC5Z2Z73L1vsduRpgIgd7KUErJrV5gRr2dmJuwH5om3dI8QiAOl\nRDAOIFfGx8NM9JYt0o4d4bK3N2xPw+RkSE2pZ3pa2rs32fEgJ6KZ8bh4DjmA0iAYB5AblUrIza5U\nZgPg6enZ7VNTyY9p9eqQI15Pd7e0alWy40EOxFNUNm8Op1CiHHICcqB0CMYB5EYWU0IGB6WuBq+k\nXV1hPzDH2NhsIB6lpgwNzQbkVFMBSoVgHEBuZDElpKcnVE3p6ZmdIe/unt3O4k3MMzAgjYzMzRGP\nAvKREaqpACVDMA7goCwtjKwnqykh69aFqinDw9L27eHywIEclDXMcvOZLI+tVWbShg3zF2s22g6g\n0AjGAUjK3sLIerKcErJihbRpk3TppeEyFzPiWW4+k+WxAUAbEYwDyOTCyHpICWmzePOZKOjNSvOZ\nLI8NANqIDpwAmloYuWlTsmNqJEoJ2bUr5IivWhVmxAnElyFe63p4eLYBTRaaz2R5bADQRnTgBKBt\n20JqSiPbt4f0CxSU+9z8n5mZ7AS7WR5b3rmHdJ+BgbnHtNF2AEtCB04ATcvqwkgkIMvNZ7I8tiIg\nLx/IBIJxAJleGIkOynLzmSyPrSjIywcyIdWccTM7W9KwpEMk7XT3P6/Z//uS3li9eqikUyQd4+6P\nmtk+SRVJv5T0RDOnAQDUFy2AXL8+xDzT02FGvKuLhZGF1qj5jBS29/eHUnuMrZjIywcyIbWccTM7\nRNLdkl4h6T5J35Z0obvf0eD2r5V0ibu/tHp9n6Q+d/9xs7+TnHFgYVNTLIwslSznDGd5bEVDXj7Q\nEc3mjKc5M36GpL3u/n1JMrNrJJ0rqW4wLulCSVcnNDaglKJa2SiJqMlMs9uTlOWxFUmjvHxmxoHE\npJkz3ivpR7Hr91W3zWNmR0g6W9I/xza7pBvMbI+ZXdzol5jZxWY2YWYTDz/8cBuGDQBAAWQpL7/I\nHVeBReRlAedrJX3d3R+NbVvn7msknSPp3Wb2knp3dPcr3L3P3fuOOeaYJMYKAED2NcrLjwLyJKup\nUNkFJZZmmsp+SSfErq+sbqvnAtWkqLj7/urlQ2Y2qpD2cmMHxgkAQPEMDEgjI3Pz76OAvL8/2Woq\n8couUhgDlV1QEmku4DxUYQHnyxSC8G9LeoO7f7fmdk+V9ANJJ7j7dHVbt6Qud69Uv/+SpD919y8s\n9DtZwAkAQEbF02YiVHZBjmW+6Y+7PyHpPZK+KOlOSf/o7t81s3eY2TtiN90g6fooEK86VtK4md0q\n6VuS/m2xQBwAAGRYvNRihEAcJZBqzri773b3X3P3/8fd/6y67XJ3vzx2m0+6+wU19/u+u59W/Xpu\ndF+UWB4X/+RxzADQKXRcRUnlZQEnsLA8Lv7J45hTUqlIO3dK27aFy0ol7RFlC8cHuZelyi5A0ty9\nNF/Pf/7zHQU1M+O+ebO7FC7rXc+aPI45BV/7mntPj3t3dzg03d3h+te+lvbIsoHjg0IYGZn/2hd/\nTRwZSXd8wDJImvAm4tPUFnCmgQWcBZfHxT95HHMbVCqh0+fkpLR6dej02dNT/3a9vfVnent6pAMH\nyt0hlOPTWc0+T9EGdFxFATW7gJNgHMWSx7bOeRxzC8bHpfXrw8Ocnpa6u8PD371bWrdu7m137pS2\nbAm3q9XdHT7DlLljKMenc5byPAWAejJfTQUZU4TFhHlc/JPHMbegUgkBTqUyG0BOT89un5qae/vJ\nyfqBZnS/vXvbP7485V4nfXzKYqnPUwBoBcE4grwvJszj4p88jrlFu3aFh1nPzEzYH7d6dZiRrKe7\nW1q1qn1jGx8PKR9btkg7doTL3t6wPauSPD5lstTnKQC0gmAcQbz7WRQI5qn7WZbaOjcrj2Nu0VJn\ncgcH52bwxHV1hf3tkNeZ0KSOT9lwxgFAkg5NewDIiHizheHh2QWFeVlMmKW2zs3K45hbFM3kNspx\nrp3J7ekJObqNcnfbtTixmZnQLOZeJ3V8ymapz9OksbAUKBYWcGKuki0mRLKWW/1jaioEH3v3hkBo\ncLC9gea2bSE1pZHt26VLL23f72u3Th+fsslylRoWlhYcVWUKpdkFnMyMY1ajxYR5mBlHLix3JnfF\nis7OTGd9JnQxnT4+ZZPVMw7xdKpI9Jxdv55SloUQrd+Kn5WOp42OjEgbNqQ9SrQZwTiC2hzxoaG5\n9a8JyNEm69aFoCFLM7mDg9LWrfX3kXtdTll8nuY1nQpLEF+/Jc19L87D+i0sC8E4gkaLCaWwvb+f\nT+Nom6XO5HY6RzarM6FIV9bOOLCwtATyvn4Ly0LOOALy1JBRSebIknuNLKPJU4mwfqsQ6MBZB8E4\nkC9ZXkgHJI3/hyYUYWIpnjYaYWY8l+jACbRR3jozFgXNV4BZUTpVT89ss6fu7tntpQ/EJRrYIZfI\nGQcWUS9NYutWSoklgRxZYK4sLizNlLwvgGT9VikRjAMLoJRYuvJechDohKwtLM2UvC+ALGEzOJCm\nAiyINIl00e4dHeEujY7OP+XfaDvyJR6QR/IQiEthjBs2zB9ro+0oBIJxYAGkSaSLHFl0RN7zirGw\nRg3s+JCFjCJNBVgAaRLpI0cWbZf3vGI0RgM75BClDYEFUEoMKCjKxxXT6Cjt5JEZ1Bmvg2Acy5Fk\n0xkACaKxSvEUoc44CoM648iNrNfwjtIkhoel7dvD5YEDBOJArpFXnK5OLaJlASRyiJxxpCovNbwp\nJQYUCHnF6YsW0ZJOAhCMIz3U8AaQChqrpI9FtMBBBONITTM1vJmNBtB2TTZWqVTC69DkZKisNDgY\nFm6jDfLenAdoIxZwIjXbtkk7djTev327dOmlyY0HwOLKEqCycDshLKJFgbGAE5kX1fCuhxreQPaM\nj4dSn1u2hA/SW7aE6+PjaY+sveIpdFHq3PT07PapqXTHVxgsogUkEYwjRbQ6B/KjTAFqMyl0aFHt\nItqZmdkccgJylAzBOFJDq3MgP8oUoE5O1u+6K4Xte/cmO55CarSINgrIx8bSHiGQGBZwIlW0Ogfy\noUwBapRCV+/xkkLXJk0uogXKgGAcqaOGN7KiLIsTl6NMAergYOh3UA8pdG0SNeFpdjtQYFRTAVAo\nyw2oqZ6xsEolLNas1yG3p6d4fQF4PgBoVbPVVAjGARTGcgOosgWay1W2AHVqihQ6AMvXbDBOmkqZ\nuIdFMfEcvYW2AznSSkdXGlA1p9k1HkVJ9yGFDkASCMbLZGxM2rhx7ur1eHmpkRFy9ZBbrQTUZVqc\n2KrFAtR6s+dbtxZ39hwAWkVpwzIZGJhfxzVe55XV68ixVgJqGlC1R5lqkQNAuxCMl0ltHdeurvl1\nXoGcaiWgpgFVe3SiFnmlIu3cKW3bFi7r5fUDQJ4RjJdNFJDHEYijAFoJqGlA1R7tTvcZHw8La7ds\nkXbsCJe9vWE7ABQFwXjZRKkpcbQeRgG0GlBHixOHh6Xt28PlgQPkOS9FO9N9SHkBUBYs4CyT2hzx\noaHZ6xIz5Mi9Vju6Uj2jNe1slkOFGwBlQTBeJmNj83PEo5SV4eHQgphqKplUlFJxSSCgTk90FqJR\nLfKlpPtQ4Qa5QulgtIBgvEwGBkL5wviLQhSQ9/dTTSWjKBWHPGn17EQkSnmpF5BT4QaZQ+lgtCDV\nDpxmdrakYUmHSNrp7n9es/+3JF0r6QfVTSPu/qfN3LceOnBmHDML89AZEmXFcx+5slAaKBXLSqvZ\nDpypLeA0s0MkXSbpHEnPkXShmT2nzk2/5u5rql9/usT7Ik+imYX4gtLoBW7jxrC/ZDpRKg7IAyrc\nZBslJ2tQOhgtSDNN5QxJe939+5JkZtdIOlfSHR2+L7Iq3pRImj+zUMI0GvJmUWbtSnlBe5E610AU\nkEfvYRKBOJqSZjDeK+lHsev3SfqNOrd7kZl9R9J+Sb/n7t9dwn1lZhdLuliSTjzxxDYMGx1Tu6A0\nekEr8cwCebMoOxbkZku85GQken1av77k6UONSgeX9P0Lzct6nfGbJZ3o7qdK+htJS85TcPcr3L3P\n3fuOOeaYtg8QbUZTojnS7gzJqWgAcaTONVCbMz4zM3uml14eWESawfh+SSfErq+sbjvI3X/m7lPV\n73dLOszMjm7mvsgpmhLNkWbeLN0PAdQida6BRqWDo4C8hGue0Lw001S+LWm1mZ2sEEhfIOkN8RuY\n2TMlPejubmZnKHx4eETSTxa7L3Io4aZEeandnUbeLKeiAdRD6lwDlA5GC9Iubbhe0l8rlCe80t3/\nzMzeIUnufrmZvUfSOyU9Iek/JW1195sa3Xex30dpw4wbHU2sTmu9BUhRY5JSL0Cq2rkzzIQ3esMd\nHiaPFygjSk4CzWu2tGGqTX+qqSe7a7ZdHvv+byX9bbP3Rc4lNLPArO/iOBUNoJ52dlkFENCBE9lh\nVn/mu9H2ZWpmAVLZZ305FQ2gEUpOAu1FMI7SYdZ3cYODoW5wPUlUcQGQbZScBNqHYBylw6zv4jgV\nDaDs8rLIH/mX6gLOpLGAExILkJZiaopT0QDKh0X+aIdcLOAE0sCsb/M4FQ2gbFjkj6QRjKOUWIAE\nAKiHRf5IGsE4SotZXwBALRb5I2ldaQ8AAAAgK6JF/vWwyB+dQDAOAABQNTgY1hDVQ2lXdALBOAAA\nQFW0yL+nZ3aGvLt7djtri9Bu5IwDAADEsMgfSSIYB4CU0FQEyC4W+SMpBOMAkIJ6TUW2bqWpCACU\nDTnjAJCweFORqITa9PTs9qmpdMcHAEgOwTgAJKyZpiIAgHIgGAeAhNFUBAAQIRgHgITRVAQAECEY\nB4CE0VQEABAhGAeAhNFUBEBmuUujo+Gyme1oGcE4AKQgaioyPCxt3x4uDxygrCGAlI2NSRs3Spdc\nMht4u4frGzeG/Wgr6owDSAUNb2gqAiCDBgakzZvDDIEkDQ2FQHx4OGwfGEh3fAVkXqLTDX19fT4x\nMZH2MIDSq9fwpquLhjcAkAnRTHgUkEshEB8akszSG1fOmNked+9b9HYE4wCSVKlIvb3hslZPT0jV\nIGcaAFLmPnel+cwMgfgSNRuMkzMOIFE0vAGAjItmxuPiOeRoK4JxJKJSkXbulLZtC5f1ZkVRDjS8\nAYAMi6eobN4cZkmiHHIC8o5gASc6rl5+8Nat5AeXVdTwpl5ATsMbAEjZ2NhsIB7liA8NhX3Dw1J/\nv7RhQ7pjLBhyxtFR5AejFs8JAMgw9xCQDwzMzRFvtB0NkTOOTCA/GLVoeAMAGWYWZr5rA+5G29Ey\n0lTQUeQHo56o4c2uXeE5sGpVqDNOIA4AKBuC8U4r+eke8oM7owgNc2h4AwAAaSqdV/K2soODc8uU\nxnV1hf1xzcWEAAAgAElEQVRYmvHxkHO9ZYu0Y0e47O0N2wEAQL4QjHdavK1sFJCXqK0s+cHtVamE\nyjSVyuzZhunp2e1TU+mODwAALA1pKp1WWxIoai1boray5Ae3TzMLYkn9AAAgP5qaGTezlWZ2VvX7\n/2Fm3Z0dVsHEA/JIuwJxd2l0dH4R/kbbUxLlB196abgkEF8eFsQCAFAsiwbjZvY2SddJ2lnd9CuS\nru3koAqnk21lS56TXjbRgth6WBALAED+NDMz/l5JL5T0M0ly97slPaOTgyqUTreVLXlOetmwIBYA\ngGJpJhj/ubv/d3TFzA6RVPxE53Zp1FY2CqBbnbmu/XldXfN/HwqDBbEAUGA5ST1Fe5kv8oc1s7+S\n9KCkt0p6l6R3S5p09/d1fnjt1dfX5xMTE8n+0qTqjLvPnTKdmSEQL7CpKRbEAkDhjI6GFNP4hFr8\njPfISOiCiVwwsz3u3rfY7ZqppvIHki6WdJekzZK+KOl/tza8Eonaxza7fTka5aQzM15YNMwBkHVF\naE6WuHjqqRTex0k9LbwFg/FqSson3P3Nkv4+mSFhSWpzxOP/uBIBOQAgcePjoffBzEyo9NTdLW3d\nGtLp1q1Le3QZRjnkUmomTWVc0lnu/otkhtQ5qaSpdBqntAAAGVKphK7Alcr8fT09oe8EaXWLIPW0\nEJpNU2lmAec9kr5mZu8zs/dGX60PEW0xMBAC7vgn5uiT9cgIp7QAAIlqpjkZFtDJcsjIpGaC8R9K\n+pKkIyQdE/tqmZmdbWbfM7O9Zra9zv43mtl3zOw2M7vJzE6L7dtX3X6LmRVsunsJotzz2k/MjbYD\nANBBNCdrQafLISOTFl3A6e5/LElm9uTq9f9sxy+u5qNfJukVku6T9G0zu87d74jd7AeS+t39MTM7\nR9IVkn4jtv8sd/9xO8YDAABaFzUnqxeQ05xsEY3KIUthe38/qacF1EwHzueY2bclTUqaNLNvmtkp\nbfjdZ0ja6+7fr9Yxv0bSufEbuPtN7v5Y9eo3JK1sw+8FAAAdQnOyFpB6WkrNpKlcIekP3X2lu6+U\n9H5J/9CG390r6Uex6/dVtzWySdLnY9dd0g1mtsfMLm7DeAAAQItoTtYCUk9LqZk64z3u/qXoirvf\nUG0ElBgzO0shGI8XRFrn7vvN7BmSvmRmd7n7jXXue7FCnXSdeOKJiYwXAIAyW7cuVE2hORmwuGaC\n8X1m9j5Jn65ef5OkfW343fslnRC7vrK6bQ4zO1XSTknnuPsj0XZ331+9fMjMRhXSXuYF4+5+hcLs\nvvr6+lj5AABAAmhOBjSnmTSVtykEzbsl/ZtC0Py2Nvzub0tabWYnm9mTJF0g6br4DczsREkjki5y\n97tj27vNrCf6XtIrJd3ehjEBAAAAiWmmmsojkt7V7l/s7k+Y2XskfVHSIZKudPfvmtk7qvsvl/S/\nJB0l6e8s5Ek9US2efqyk0eq2QyV91t2/0O4xAstFG2gAANCMZjpwfkHSBe7+k+r1p0v6P+7+6gTG\n11aF7MCJpiUVINdrA93VRRtoAADKpNkOnM3kjB8bBeKSVK35fXxLowMSVi9A3rq1/QFypRJ+T7wN\ndFRrd/162kADAIC5mskZnzGzg/W9q3ncQG7EA+QoMJ6ent0+NdW+30UbaAAAsBTNBOP/S9LXzewT\nZvZJhYolf9jRUQFtlGSATBtoAACwFM0s4Pw3MztD0pkKjXb+wN0f6vjIgDZJMkCmDTQAAFiKhjPj\nZnaCmT1Fktz9QUmPSnqJpAvM7LCExge0LAqQ62l3gEwbaAAAsBQLpal8TtJTJMnMTpM0KukhheY6\nl3V+aEB7JBkg0wYaAAAsxUJpKke4+33V79+kUAf8L8ysS9KtnR8a0B5RINyo3GC7A2TaQAMAgGYt\nFIxb7PuXSnq/JLn7jJnRVh65knSATBvoxdEYCQCAhYPx/2tmn5V0v0IXzK9Ikpk9U9IvEhgb0FYE\nyNmRVN13AACybqGc8fdK2i3pAUm/6e7/Xd1+vKQ/7vTAABRTknXfAQDIuoYz4+4+I+n/1Nl+c0dH\nBKDQmqn7zhkMABLpbCiHReuMA0A70RgJQDNIZ0NZNNOBEwDaJsm67wDyiXQ2lAnBOIBE0RgJwGKa\nSWcDimKhDpw9ZvYhM/uEmb2+Zt/fdH5oAIqIxkgAFkM6G8pkoZzxKyXdK+nfJL3NzH5b0pvc/ReS\nXpzE4AAUE42RACwkSmerF5CTzoaiMff6/XvM7BZ3XxO7/gFJL5f0Oklfdve1yQyxffr6+nxiYiLt\nYQAAgAVUKlJvb7is1dMTPszz4R1ZZ2Z73L1vsdstlDN+uJkd3O/ufyLpk5JulHRkyyMEAACog3Q2\nlMlCaSr/Jullkr4UbXD3j5vZA5L+ttMDAwAA5UU6G8qiYZpKEZGmAgAAgCS0I00FAAAAQAcRjAMA\nAAApWTQYN7N5eeX1tgEAAACpcJdGR8NlM9szpJmZ8W81uQ0AAABI3tiYtHGjdMkls4G3e7i+cWPY\nn1ENZ7jN7BmSjpP0ZDN7niSr7nqKpCMSGBsAAACwuIEBafNmaXg4XB8aCoH48HDYPjCQ7vgWsFC6\nyaslvU3SSkmXaTYYr0j64w6PCwAAAFnmHmacBwYks8W3d5JZCMClEIBHQfnmzWF7UuNYhkVLG5rZ\n6939HxMaT0dR2hAAAKBNRkdDCkg84I1SQ4aHpZERacOGZMfkLnXFsrBnZlILxNtZ2vAZZvaU6g+9\n3My+ZWYva3mEAAAAyK94akiUq51makj0++PiOeQZ1UwwfrG7/8zMXqmQQ/47knZ0dlgAAADItCg1\nJArIu7pmA/GkU0NqPwjMzMz/oJBRzQTj0ejXS/qUu9/a5P0AAABQZPFc7UgaOdpjY/M/CMQ/KGS4\nmkozQfWtZrZb0mskfd7MVmg2QAcAAEBZZSU1ZGAg5KjHPwhEAfnISKarqTQTjL9V0gclneHuj0s6\nXNKmTg4KAAAAGZel1BCzsFi0dka+0fYMWbSTprv/0sx+VdIrJP2ZpCeLNBUAAIBya5QaIoXt/f3J\nV1PJoWZKG/6tpMMkvcTdTzGzIyV90d1fkMQA24nShgAAAG2SpTrjGdTO0oYvcve3S/q5JLn7o5Ke\n1OL4kDXuoV5o7YezRtsBAEC55Tg1JEuaCcZ/YWZdqi7aNLOjJM10dFRI3thYKNwfz/GKcsE2bsz0\nKuSiqFSknTulbdvCZaWS9ogAAECnNcwZN7ND3f0JSZdJ+mdJx5jZn0h6vaQ/SWh8SEq8cL8Ucr7S\nLNxfMuPj0vr1Ye3L9LTU3S1t3Srt3i2tW5f26AAAQKc0zBk3s5vdfW31++dKerkkk3SDu9+e3BDb\nh5zxRcRXRUfSKNxfMpWK1Ntbfya8p0c6cEBasaLzY9i1S5qclFavlgYHw+8GAADL02zO+ELB+P/n\n7qe3fWQpIhhvgnvooBWZmSEQ77CdO6UtW8KMeK3u7vDZaFMHi4nWm5Xv6mJWHgCAVjQbjC9U2vAY\nM9vaaKe7f3RZI0N2NSrcz8x4R01O1g/EpbB9797O/e5KJQTi8Vn5aCzr1yczKw8AQJkttIDzEEkr\nJPU0+EKRZKlwf8msXh1mo+vp7pZWrerc7961K/yp65mZCfsB5AOLwNF2VFpLxEIz4/e7+58mNhKk\nK0OF+8uWvzw4GBZr1tPVFfZ3Spqz8gDah0Xg6Iio0lo8NohP3o2M0NSnDRYKxslLKJOBgfBPFS/Q\nHwXk/f2JVVMp4xtKT094fI3ytjuZJhLNyjfKV+/krDyA9iDdDB1DpbVELLSA88hqg5/O/XKzsyUN\nK6TE7HT3P6/Zb9X96yU9Lul/uvvNzdy3HhZwZlsWqoqkaWoqnBHYuzcEwYODyVRRKfMxB4og7UXg\nKDgqrS1byx04EwjED1GoYX6OpOdIutDMnlNzs3Mkra5+XSzp75dwX+RM2fOXV6wIb5iXXhoukwiC\no1n5np7ZvPXu7tntBOJA9pFuho6Kp61GCMTbaqE0lU47Q9Jed/++JJnZNZLOlXRH7DbnSvqUh+n7\nb5jZ08zsOEknNXFf5AxvKOlYty7MgCc9Kw+gPUg3Q0dRaa3j0gzGeyX9KHb9Pkm/0cRtepu8L3KG\nN5T0RLPynVa2xblAEtJcBI6Cq620Fs8ZlwjI22Sh0oaFYGYXm9mEmU08/PDDaQ8HCxgcnNtvKI43\nlPwbHw/56Vu2SDt2hMve3rAdwPKRboaOaVRpLVrUOTaW9ggLIc2Z8f2STohdX1nd1sxtDmvivpIk\nd79C0hVSWMDZ2pDRSWlWFUFnUe0B6CzSzdARGam0VnRpBuPflrTazE5WCKQvkPSGmttcJ+k91Zzw\n35D0U3e/38webuK+yCHeUIqpmcW5VHsAWpNUulli3MPMazwQXGg72s+sfh3xRtuxLKkF4+7+hJm9\nR9IXFcoTXunu3zWzd1T3Xy5pt0JZw70KpQ3futB9U3gY6IDCvaGAxbkAlo6GMyiJNGfG5e67FQLu\n+LbLY9+7pHc3e18A2cTiXABLRsMZlETDpj9FRNMfIB00FwKwLDScQY613PQHANqFag8AloWGMyiB\nVNNUAJQHi3MBLBkNZ1ACzIwDmOUujY6Gy2a2L1G0OPfSS8MlgTiAhmobzszMzOaQX3JJy69HQFYQ\njAOYFVUviL/RRW+IGzfS4AFAcmg4g5IgGEfyOjz7ihbEqxdEATnVCwCkIWo4E09JiQLyqBENUAAE\n40ges6/ZVTvz1NU1f2YKAJIQNZapfd1ptB3IKYJxJI/Z12yjegEAAIkhGC+DrKWFMPuabY2qF5A+\nBADZk7X3eCwZwXgZZDEthNnXbKJ6AQDkSxbf47EkBONlkMW0EGZfs4nqBQCQL1l8j8eSmJco+Onr\n6/OJiYm0h5GOLLUUrn2hGBqaf50Z8nS4h4B7YGDu36DRdgBA+rL0Ho+DzGyPu/ctejuC8RJxD/nZ\nkZmZdP5JR0fDqbP4C0X8hWRkJKyUBwAAzcnKezwOajYYJ02lLLKUFkLtWAAA2idL7/FYMoLxMsja\nojxqxwIA0B5Ze4/Hkh2a9gCQgEaL8qSwvb+ftBAAAPKI9/jcI2e8DFiUBwBAMfEen1ks4KyjtME4\nAAAAEsUCTqDd6HIGAADajGAcaBZdzgAAQJuxgBNoVrzLmTS/WRElGQGg4yoVadcuaXJSWr1aGhyU\nenrSHhWwfOSMA0tBlzMASM34uLR+fajeNz0tdXeHPje7d0vr1qU9OmAuFnDWQTCOtqDLGQAkrlKR\nenvDZa2eHunAAWnFiuTHBTTCAk6gE+hyBgCp2LUrzH3UMzMT9gN5RDAONIsuZ8iBSkXauVPati1c\n1ptFBPJocjKkptQzPS3t3ZvseIB2YQEn0Cy6nCHj6uXTbt1KPi2KYfXq8JyuF5B3d0urViU/JqAd\nyBkHmkWXM2QY+bQoOp7jyBtyxoF2Mwsz37UBd6PtQILIp0XR9fSEszw9PWEmXAqX0XYCceQVaSoA\nUADk06IM1q0LM+C7doXn9KpVoc44gTjyjGAcAJYgqw1HyKfFQrL6vF2OFSukTZuS/Z1FOn7IHnLG\ngRLjDWZpstxwhHxaNJLl520ecPywXDT9qYNgHJjFG8zS5CHY5W+KWnl43mYZxw+tYAEngIYqlRC0\nVSqzaQ3T07Pbp6bSHV8W5WGBZJRPOzwsbd8eLg8cIBAvszw8b7OM44ckEIwDJcQbzNLlZYFklE97\n6aXhklm7csvL8zarCnf83KXR0flN6hptRyIIxoESKtwbTAKiBZL1sEASWcXztjWFO35jY9LGjXO7\nRkfdpTduDPuROIJxLB2frHOv028wRWzJPjgY8q/r6eoK+4Gs4XnbmsIdv4GB0EV6eHg2IL/kktnu\n0gMDaY+wlAjGsXR8ss69Tr7BjI+HBU9btkg7doTL3t6wPc9oOII84nnbmsIdPzNpaGg2IO/qmg3E\nh4ZoXpcSqqlg6Wo/SQ8Nzb/OP3TmdaLyRhkqD0xN0XAE+cPztjWFO37uc2dkZmZ43+4AShvWQTDe\nRvGAPEIgnjvtfoPZuTPMhDdqPDM8nHyzDqAeauyjtHj/TkyzwTgdOLE80amu+D8z/8i50+5OdiwM\nRR7UOyu0dSv12FECC53ZlngfTwk541ie6B86Lp5DjlIqXOUBFA419lFqY2PzU0rjOeSs+UoFwTiW\nrvaT9czM/NXZKKXCVR5A4VBjP7+KWKUpcQMD0sjI3BnwKCAfGaGaSkpIU8HSNfpkLYXt/f3Shg3p\njhGpiCoMNFoYmusFTygEUqnyidSiNjGr//7caDsSkUowbmZHStol6SRJ+yS93t0fq7nNCZI+JelY\nSS7pCncfru77oKTfkfRw9eZ/6O67kxg7NPvJemBg/ifr/n4+WZdc1JK9UJUHUBhRKlWjRcakUmVP\nPLUoEv391q8vRpUmlFtaaSrbJX3Z3VdL+nL1eq0nJP2/7v4cSS+U9G4ze05s/5C7r6l+EYhLyTXj\niT5B1y7yaLQdzSlQMyVasiOrSKXKH1KLUHRpBePnSrqq+v1VkuZNpbr7/e5+c/X7iqQ7JfUmNsI8\nohlPvvH3AzqucE1cSoDUIhRdWjnjx7r7/dXvH1BIRWnIzE6SdLqkb8Y2/66ZvVnShMIM+mN17ioz\nu1jSxZJ04okntjbqrIu3uZXmN+MhfSTb+PsBiSCVKl9ILULRdazpj5ndIOmZdXa9X9JV7v602G0f\nc/enN/g5KyT9X0l/5u4j1W3HSvqxQi75hyQd5+5vW2xMpWj6QzH/TFu00Qh/v5bRzAUoljJ09kUx\nZboDp5l9T9Jvufv9ZnacpH9392fVud1hkv5V0hfd/aMNftZJkv7V3X99sd9bimBcos1tRjXdfp6/\n37I1fYwB5Ar/28ijZoPxtHLGr5P0lur3b5F0be0NzMwkfVzSnbWBeDWAj2yQdHuHxpk/NOPJpKYb\njfD3WzaauQDFFaUWDQ9L27eHywMHCMRRDGkF438u6RVmNinp5dXrMrPjzSyqjPJiSRdJeqmZ3VL9\nWl/dt8PMbjOz70g6S1JN9FJSNOPJrKaqAfD3awkVF4Bio0oTiiqVBZzu/oikl9XZfkDS+ur345Lq\nnpt394s6OsC8ohlPZjVVDYC/X0uouAAAyCM6cBYJzXgyq6lqAPz9WkLFBQBAHqWygDMtpVnAieVz\nDzPU8YB4oe1NohpA53GMAQBZkvUFnEA2dajxDo1GOo9jDADII9JUgLgONt6h0UjncYwBAHlDmgpQ\ni8Y7AACgRZlu+pMWgnE0jcY7AACgBeSMA8tF4x0AAJAQgnEgjsY7AAAgQSzgBOJovAMAABJEMA7E\n0XgHAAAkiGAciDOrP/PdaDsAAEALyBkHAAAAUkIwDgAAAKSEYBwAAABICcE4AAAAkBKCcQD55S6N\njs6v/95oOwDkHa97hUMwDiC/xsakjRvnNmSKGjdt3Bj2A0CR8LpXOJQ2BJBfAwOzHVKlUA8+3kGV\nuvAAiobXvcIxL9HpjL6+Pp+YmEh7GADaKZoRit6YpLkdVAGgaHjdywUz2+PufYvejmAcQO65S12x\nrLuZGd6QABQbr3uZ12wwTs44gHyLZoji4rmUAFA0vO4VCsE4gPyKn6rdvDnMDEW5lA3emCoVaedO\nadu2cFmppDBuAFiuZbzuIdtYwAkgv8bGZt+QolzJoaGwb3hY6u+XNmw4ePPxcWn9+vDeNT0tdXdL\nW7dKu3dL69al9BgaqFSkXbukyUlp9WppcFDq6Ul7VABSt8TXPWQfOeMA8ss9vDENDMzNlayzvVKR\nenvrz4T39EgHDkgrViQ07kXU+9DQ1ZXNDw0AEraE1z2ki5xxIKto2NA+ZmEGqPaNp872XbtCcFvP\nzEzYnwWVSgjEK5UQiEvhMto+NZXu+NJAahEQs4TXPeQDwTjSV7bglIYNqZicnA1ua01PS3v3Jjue\nRvLyoSEp4+PhjMaWLdKOHeGytzdsR0zZXkeBAiEYR/rKFpzGGzZEj5mGDR23enVI96inu1tatSrZ\n8TSSlw8NSeAswRKU7XUUKBCCcaSvbMFptNgmesxdXfMX46DtBgfnluSN6+oK+7MgLx8aksBZgiUo\n2+soUCAs4EQ2lLGbGA0bEpeHhZF5Wmjaadu2hdSURrZvly69NLnxZF4ZX0eBDGMBJ/IlXpopUuQ3\nEBo2pGLduhDMDg+HQG54OFzPSiAuhYB79+5wGc2Qd3fPbi9LIC5xlmDJyvY6ChQEwTiyoUzBKQ0b\nUrVihbRpU5hR3bQpm8FtHj40JCEvqUWZUabXUaBACMaRvrIFp40aNkSPmYVWrSlIVYk8fGjoNM4S\nLEHZXkeBAiFnHOkbHQ2r/ePBafyNZWSkWN3EaNjQWWV7PpXA1FRYrLl3b0hNGRwkEJ+H5z2QOc3m\njBOMI30Ep2in2hnCoaH513k+oWh4HQUyh2C8DoJxoCSoKgEASBnBeB0E40CJUDoSAJAiShsCKC+q\nSgAAcoJgHECxUFUCAJAjh6Y9AABoq0alI6Wwvb+fqhIAgMwgGAdQLAMDoYxbvHpEFJD394ftAABk\nBME4gGIxqz/z3Wg7AAApImccAAAASAnBOAAAAJCSVIJxMzvSzL5kZpPVy6c3uN0+M7vNzG4xs4ml\n3h8AAADIsrRmxrdL+rK7r5b05er1Rs5y9zU1RdOXcn8AAAAgk9IKxs+VdFX1+6skLbW8Qav3BwAs\nQaUi7dwpbdsWLiuVtEcEAMVgnkIDDDP7ibs/rfq9SXosul5zux9I+qmkX0r63+5+xVLuX91/saSL\nJenEE098/r333tuJhwQAhTU+Lq1fH/onTU9L3d1SV5e0e7e0bl3aowOAbDKzPTWZHXV1bGbczG4w\ns9vrfJ0bv52HTwONPhGsc/c1ks6R9G4ze0ntDRa5v9z9Cnfvc/e+Y445poVHBADlU6mEQLxSCYG4\nFC6j7VNT6Y4PncdZkRS4S6Oj8zsGN9qOXOtYMO7uL3f3X6/zda2kB83sOEmqXj7U4Gfsr14+JGlU\n0hnVXU3dHwDQml27wox4PTMzYT+Ka3xc6u2VtmyRduwIl729YTs6aGxM2rhRuuSS2cDbPVzfuDHs\nR2GklTN+naS3VL9/i6Rra29gZt1m1hN9L+mVkm5v9v4AgNZNTs7OiNeanpb27k12PEgOZ0VSNDAg\nbd4sDQ/PBuSXXBKub95MJ+GCSasD559L+kcz2yTpXkmvlyQzO17STndfL+lYSaMhJVyHSvqsu39h\nofsDANpr9eqQI14vIO/ullatSn5MaKxSCWcrJifD325wUOrpWd7PauasyKZNyx9rJ7XzOKTCTBoa\nCt8PD4cvKQTiQ0NhPwojlQWcaenr6/OJiYnFbwgAkBSCmt7e+nnCPT3SgQPSihXJjwvztXuh7bZt\nITWlke3bpUsvXf54O6VQC47dw+AjMzME4jmS+gJOAED+9fSEIKanJwQ1UriMthOIZ0MnUkqisyL1\nZPWsSKFSa6LUlLh4DjkKg2AcALCgdevCDPjwcJgNHR4O13M3y1hgnVhoOzg4d1I2rqsr7M+awiw4\nrs0Rn5mZn0OOwkgrZxwAkCMrVmQ3PxidWWgbnf1olPKRxbMimV5w7B6qoAwMzE01qbd9bGw2EI9y\nxOM55P390oYNyT8GdAQz4wAA5FynUkrydlYk06k1SylXODAgjYzMXawZBeQjI1RTKRgWcAIAkIBO\nVvhgoW2Q6eNQm3oyNDT/OoszC6XZBZykqQAA0GH1Knxs3dq+Ch95TCnphEwfB8oVogFmxgEA6KAk\nZ2unpsLs+969ISVjcLA8gXhcpo8D5QpLg9KGAJAEd2l0dH51g0bbi6KsjzuyhMefZIWPaKHtpZeG\ny8wEoAnL7HGgXCHqIBgHgFYsZVFWkZT1cUeW8PgzXeEDyaFcIRogZxwAWjEwMPuGKs1flFXUqgdl\nfdyRJTz+qMJHvYA89QofSA7lCtEAOeMA0Kr4jFekDIuyyvq4I00+/kxX+IhbSh1sLB3Ht3SazRkn\nGAeAdijroqwWH3cny/0losnHX6+aSlThIzM1u0dHQ4pN/ANF/APHyAgzt8ASsIATAJJS1kVZLT7u\n8fEwY7xli7RjR7js7Q3bc2EJjz8XzXPiqTfR4yhT6hGQFncvzdfzn/98B4C2mplx37zZXQqX9a4X\nUYuP+2c/c+/pCTev/erpca9UEnocy1XUv3v8cURfeX48QIokTXgT8Skz4wDQikaLsqIZxqJWFWnx\ncSdZ7q8jivp3jy8qjJRlDQCQEqqpAEArBgZCLm188VUU0PT3F/fUfouPO/fl/or6d2+UekNADnQM\nM+MA0AqzsKitNlBptL0oWnzcUbm/enJR7q+If3fqYAOpIBgHACRucHBuEZK4rq6wHwkrauoNkHEE\n4wCAxPX0hLJ+PT2zM+Td3bPbM1F3u2yi1Jt4SkoUkEcpOQDajjrjANqHphZYoqmpsFhz796QmjI4\nSCAOoBiarTPOAk4A7TM2RtMQLMmKFdKmTWmPAgDSQzAOoH3iTUOkEJDTNAQAgIYIxgG0T7xG8fDw\nbFAenykHAAAHkTMOoP3c55bKmJkhEAcAlEqzOeNUUwHQXo2ahpTogz8AAM0iGAfQPjQNAQBgScgZ\nB9A+jZqGSGF7fz/VVAAAiCEYB9A+UdOQeD3xKCDv76eaCgAANQjGAbSPWf2Z70bbAQAoOXLGAQAA\ngJQQjAMAAAApIRgHAAAAUkIwDgAAAKSEYBwAAABICcE4AAAAkBKCcQAAACAlBOMAAABASgjGAQAA\ngJQQjAMAAAApIRgHAAAAUkIwDgAAOs9dGh0Nl81sB0qCYBwAAHTe2Ji0caN0ySWzgbd7uL5xY9gP\nlNChaQ8AAACUwMCAtHmzNDwcrg8NhUB8eDhsHxhId3xASlKZGTezI83sS2Y2Wb18ep3bPMvMbol9\n/czMtlT3fdDM9sf2rU/+UQBAjpAigLSZhQA8Csi7umYD8aGhsB8oobTSVLZL+rK7r5b05er1Odz9\ne/K36qIAAAtmSURBVO6+xt3XSHq+pMcljcZuMhTtd/fdiYwaAPKKFAFkQRSQxxGIo+TSCsbPlXRV\n9furJC12buplku5x93s7OioAKKp4ikAUkJMigKRFz7u4+AdEoITSCsaPdff7q98/IOnYRW5/gaSr\na7b9rpl9x8yurJfmEjGzi81swswmHn744RaGDAA5VvYUAdJ00lf7AXBmZv4HRKCEzDv05DezGyQ9\ns86u90u6yt2fFrvtY+5eN6A2sydJOiDpue7+YHXbsZJ+LMklfUjSce7+tsXG1NfX5xMTE0t+LABQ\nGO4hEI/MzBQ/EJdCwL1x49wPH/HgcGRE2rAh7VEWG38DlIyZ7XH3vsVu17FqKu7+8kb7zOxBMzvO\n3e83s+MkPbTAjzpH0s1RIF792Qe/N7N/kPSv7RgzABRaoxSBMsyMU8kjfQMDIeAeGJh9vkVnbPr7\n+RugtNJKU7lO0luq379F0rUL3PZC1aSoVAP4yAZJt7d1dABQNGVPESh7mk4WmIWZ79pj3Wg7UBId\nS1NZ8JeaHSXpHyWdKOleSa9390fN7HhJO919ffV23ZJ+KOlX3f2nsft/WtIahTSVfZLeHstBb4g0\nFQClRYpAUNY0HQCJazZNJZVgPC0E4wBKyz2UL4ynCCy0vYjiHz4izIwD6JBmg/G00lQAAEkqe4pA\n2dN0AGRWxxZwAgCQGWNj83PEo+Yzw8NhAWEZ0nQAZA7BOACg+KjkASCjCMYBAMUXpeM0ux0AEkLO\nOAAAAJASgnEAAAAgJQTjAAAAQEoIxgEAAICUEIwDAAAAKSEYBwAAAFJCMA4AAACkhGAcAAAASAnB\nOAAAAJASgnEAAAAgJQTjAAAAQEoIxgEAAICUEIwDAAAAKSEYBwAAAFJCMA4AAACkhGAcAAAASAnB\nOAAAAJASc/e0x5AYM3tY0r1pjyMBR0v6cdqDyDGO3/Jx7FrD8Vs+jt3ycexaw/FbvqIfu19x92MW\nu1GpgvGyMLMJd+9Lexx5xfFbPo5dazh+y8exWz6OXWs4fsvHsQtIUwEAAABSQjAOAAAApIRgvJiu\nSHsAOcfxWz6OXWs4fsvHsVs+jl1rOH7Lx7ETOeMAAABAapgZBwAAAFJCMA4AAACkhGA8p8zsSDP7\nkplNVi+fXuc2zzKzW2JfPzOzLdV9HzSz/bF965N/FOlo5thVb7fPzG6rHp+Jpd6/qJp87p1gZl81\nszvM7Ltmtjm2r3TPPTM728y+Z2Z7zWx7nf1mZh+r7v+Oma1t9r5F18Sxe2P1mN1mZjeZ2WmxfXX/\nh8ukieP3W2b209j/4/9q9r5F18Sx+/3YcbvdzH5pZkdW95X6uWdmV5rZQ2Z2e4P9vObFuTtfOfyS\ntEPS9ur32yX9xSK3P0TSAwoF6CXpg5J+L+3HkeVjJ2mfpKNbPfZF+2rm8Us6TtLa6vc9ku6W9Jzq\n9VI996r/e/dI+lVJT5J0a3QsYrdZL+nzkkzSCyV9s9n7FvmryWP3IklPr35/TnTsqtfr/g+X5avJ\n4/dbkv51Ofct8tdSH7+k10r6Sux62Z97L5G0VtLtDfbzmhf7YmY8v86VdFX1+6skDSxy+5dJusfd\ny9CBdDFLPXbtvn/eLfr43f1+d7+5+n1F0p2SehMbYbacIWmvu3/f3f9b0jUKxzDuXEmf8uAbkp5m\nZsc1ed8iW/Txu/tN7v5Y9eo3JK1MeIxZ1srzh+fe0h7/hZKuTmRkOeDuN0p6dIGb8JoXQzCeX8e6\n+/3V7x+QdOwit79A818ofrd6eujKkqVaNHvsXNINZrbHzC5exv2LakmP38xOknS6pG/GNpfpudcr\n6Uex6/dp/geTRrdp5r5FttTHv0lhti3S6H+4LJo9fi+q/j9+3syeu8T7FlXTj9/MjpB0tqR/jm0u\n+3NvMbzmxRya9gDQmJndIOmZdXa9P37F3d3MGtaoNLMnSXqdpPfFNv+9pA8pvGB8SNJfSXpbq2PO\nijYdu3Xuvt/MniHpS2Z2V/XTfrP3z602PvdWKLxBbXH3n1U3F/q5h3SY2VkKwfi62OZF/4ehmyWd\n6O5T1fUbY5JWpzymvHmtpK+7e3wmmOcemkYwnmHu/vJG+8zsQTM7zt3vr57aeWiBH3WOpJvd/cHY\nzz74vZn9g6R/bceYs6Idx87d91cvHzKzUYXTZzdKWsqxz6V2HD8zO0whEP+Mu4/Efnahn3t17Jd0\nQuz6yuq2Zm5zWBP3LbJmjp3M7FRJOyWd4+6PRNsX+B8ui0WPX+xDstx9t5n9nZkd3cx9C24pj3/e\nmWeee4viNS+GNJX8uk7SW6rfv0XStQvcdl4uWzWIimyQVHfFc0EteuzMrNvMeqLvJb1Ss8doKce+\niJo5fibp45LudPeP1uwr23Pv25JWm9nJ1bNUFygcw7jrJL25WmHghZJ+Wk0Faua+Rbbo4zezEyWN\nSLrI3e+ObV/of7gsmjl+z6z+v8rMzlCICx5p5r4F19TjN7OnSupX7HWQ515TeM2LS3sFKV/L+5J0\nlKQvS5qUdIOkI6vbj5e0O3a7boUX1qfW3P/Tkm6T9B2FJ/pxaT+mLB07hZXct1a/vivp/Yvdvyxf\nTR6/dQppKN+RdEv1a31Zn3sKlQPuVqgS8P7qtndIekf1e5N0WXX/bZL6Frpvmb6aOHY7JT0We55N\nVLc3/B8u01cTx+891eNzq8IC2Bfx3Gvu2FWv/09J19Tcr/TPPYUJwPsl/UIh73sTr3mNv6z6wAEA\nAAAkjDQVAAAAICUE4wAAAEBKCMYBAACAlBCMAwAAACkhGAcAAABSQjAOADlgZkeZ2S3VrwfMbH/s\n+pOW8HPeZmb1uqvKzAbN7A4zmzGzNQ1uc4iZXWZmt5vZbWb2LTP7leU+LgAoOzpwAkAOeOgsuUaS\nzOyDkqbc/S+X8aPeptAC/YE6+26TNCDpygXu/waFWvOnuvtMtenOzxa4/aLM7FB3f6KVnwEAeUUw\nDgA5Z2ZvkfRuSU+SdJNCI5cuSZ9QCOBN0hWSHqxe32Vm/ynpDHf/7+jnuPsd1Z+30K87TtL97j5T\nvc8PY+N4taQPSTpE0oPu/spqa/UrJZ0kaUrSxe5+u5n9/+3dP2hWVxzG8e9TClakqKWCLllKSYXG\nQdtOWrSIUAJKKJaCS7sUDXV2UpB2chFcpK1Ghw6FTg4VDJGAGVTIEOwsJZZ2CFIECURs+XW4Rwj+\nWV4Clzf9fuCF+9577j33faeHw++c8x0wArwD/J7kS+Ac3YZRbwAXqurS4P+KJA0Hw7gkDbEk7wMT\ndDsn/pPkB7otpO8Db1fVWGu3paoeJTkJfFNVCwN2+TMwl2Q/3U6sP1XVQit9uQjsq6rFJG+19t8C\nd6vqcJJDwFXgg3btPeDjqlpJMgksVdVHSTYAd5JMrw77krQeGcYlabgdBD4E5tuI9kbgD+AGMJrk\nAvArML0WnVXVgySjwCftM5tkAtgKzFbVYmv3d7tlLzDezk0nuZpkU7t2rapW2vEhYGeSL9r3zcC7\ngGFc0rpmGJek4RZgqqpOv3Ah2QV8SlfC8hnw9Vp02AL0deB6kofAEeDWAI9aXnUcYLKqbq7BK0rS\n0HA1FUkabjPA5602+9mqKyNJtgGpql+AM8Du1v4x8OagnSXZk2RHO34NGAMW6WrVDzxbWWVVmcoc\ncKydOwj8WVXLLzy4G8mfTPJ6azuaZOOg7ylJw8KRcUkaYlX1W5KzwEwLx0+B48C/wOV0tSsFnGq3\nXAEuvWwCZ5KjwHlgG3AjyXxVjT/X5Xbgx7acYoDbwMWqepLkBHCt9fkX3aj8GWAqyT26CZxfveKn\nfE83oXOhldss0Y24S9K6lqrq+x0kSZKk/yXLVCRJkqSeGMYlSZKknhjGJUmSpJ4YxiVJkqSeGMYl\nSZKknhjGJUmSpJ4YxiVJkqSe/AeUxWiWnpvoUgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x99d4940>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "positive = data2[data2['Accepted'].isin([1])]\n",
    "negative = data2[data2['Accepted'].isin([0])]\n",
    "\n",
    "fig, ax = plt.subplots(figsize=(12,8))\n",
    "ax.scatter(positive['Test 1'], positive['Test 2'], s=50, c='b', marker='o', label='Accepted')\n",
    "ax.scatter(negative['Test 1'], negative['Test 2'], s=50, c='r', marker='x', label='Rejected')\n",
    "ax.legend()\n",
    "ax.set_xlabel('Test 1 Score')\n",
    "ax.set_ylabel('Test 2 Score')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "哇，这个数据看起来可比前一次的复杂得多。特别地，你会注意到其中没有线性决策界限，来良好的分开两类数据。一个方法是用像逻辑回归这样的线性技术来构造从原始特征的多项式中得到的特征。让我们通过创建一组多项式特征入手吧。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>Accepted</th>\n",
       "      <th>Ones</th>\n",
       "      <th>F10</th>\n",
       "      <th>F20</th>\n",
       "      <th>F21</th>\n",
       "      <th>F30</th>\n",
       "      <th>F31</th>\n",
       "      <th>F32</th>\n",
       "      <th>F40</th>\n",
       "      <th>F41</th>\n",
       "      <th>F42</th>\n",
       "      <th>F43</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>0.051267</td>\n",
       "      <td>0.002628</td>\n",
       "      <td>0.035864</td>\n",
       "      <td>0.000135</td>\n",
       "      <td>0.001839</td>\n",
       "      <td>0.025089</td>\n",
       "      <td>0.000007</td>\n",
       "      <td>0.000094</td>\n",
       "      <td>0.001286</td>\n",
       "      <td>0.017551</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.092742</td>\n",
       "      <td>0.008601</td>\n",
       "      <td>-0.063523</td>\n",
       "      <td>-0.000798</td>\n",
       "      <td>0.005891</td>\n",
       "      <td>-0.043509</td>\n",
       "      <td>0.000074</td>\n",
       "      <td>-0.000546</td>\n",
       "      <td>0.004035</td>\n",
       "      <td>-0.029801</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.213710</td>\n",
       "      <td>0.045672</td>\n",
       "      <td>-0.147941</td>\n",
       "      <td>-0.009761</td>\n",
       "      <td>0.031616</td>\n",
       "      <td>-0.102412</td>\n",
       "      <td>0.002086</td>\n",
       "      <td>-0.006757</td>\n",
       "      <td>0.021886</td>\n",
       "      <td>-0.070895</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.375000</td>\n",
       "      <td>0.140625</td>\n",
       "      <td>-0.188321</td>\n",
       "      <td>-0.052734</td>\n",
       "      <td>0.070620</td>\n",
       "      <td>-0.094573</td>\n",
       "      <td>0.019775</td>\n",
       "      <td>-0.026483</td>\n",
       "      <td>0.035465</td>\n",
       "      <td>-0.047494</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>1</td>\n",
       "      <td>1</td>\n",
       "      <td>-0.513250</td>\n",
       "      <td>0.263426</td>\n",
       "      <td>-0.238990</td>\n",
       "      <td>-0.135203</td>\n",
       "      <td>0.122661</td>\n",
       "      <td>-0.111283</td>\n",
       "      <td>0.069393</td>\n",
       "      <td>-0.062956</td>\n",
       "      <td>0.057116</td>\n",
       "      <td>-0.051818</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   Accepted  Ones       F10       F20       F21       F30       F31       F32  \\\n",
       "0         1     1  0.051267  0.002628  0.035864  0.000135  0.001839  0.025089   \n",
       "1         1     1 -0.092742  0.008601 -0.063523 -0.000798  0.005891 -0.043509   \n",
       "2         1     1 -0.213710  0.045672 -0.147941 -0.009761  0.031616 -0.102412   \n",
       "3         1     1 -0.375000  0.140625 -0.188321 -0.052734  0.070620 -0.094573   \n",
       "4         1     1 -0.513250  0.263426 -0.238990 -0.135203  0.122661 -0.111283   \n",
       "\n",
       "        F40       F41       F42       F43  \n",
       "0  0.000007  0.000094  0.001286  0.017551  \n",
       "1  0.000074 -0.000546  0.004035 -0.029801  \n",
       "2  0.002086 -0.006757  0.021886 -0.070895  \n",
       "3  0.019775 -0.026483  0.035465 -0.047494  \n",
       "4  0.069393 -0.062956  0.057116 -0.051818  "
      ]
     },
     "execution_count": 29,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "degree = 5\n",
    "x1 = data2['Test 1']\n",
    "x2 = data2['Test 2']\n",
    "\n",
    "data2.insert(3, 'Ones', 1)\n",
    "\n",
    "for i in range(1, degree):\n",
    "    for j in range(0, i):\n",
    "        data2['F' + str(i) + str(j)] = np.power(x1, i-j) * np.power(x2, j)\n",
    "\n",
    "data2.drop('Test 1', axis=1, inplace=True)\n",
    "data2.drop('Test 2', axis=1, inplace=True)\n",
    "\n",
    "data2.head()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在，我们需要修改第1部分的成本和梯度函数，包括正则化项。首先是成本函数："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# regularized cost（正则化代价函数）\n",
    "$$J\\left( \\theta  \\right)=\\frac{1}{m}\\sum\\limits_{i=1}^{m}{[-{{y}^{(i)}}\\log \\left( {{h}_{\\theta }}\\left( {{x}^{(i)}} \\right) \\right)-\\left( 1-{{y}^{(i)}} \\right)\\log \\left( 1-{{h}_{\\theta }}\\left( {{x}^{(i)}} \\right) \\right)]}+\\frac{\\lambda }{2m}\\sum\\limits_{j=1}^{n}{\\theta _{j}^{2}}$$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def cost(theta, X, y, learningRate):\n",
    "    theta = np.matrix(theta)\n",
    "    X = np.matrix(X)\n",
    "    y = np.matrix(y)\n",
    "    first = np.multiply(-y, np.log(sigmoid(X * theta.T)))\n",
    "    second = np.multiply((1 - y), np.log(1 - sigmoid(X * theta.T)))\n",
    "    reg = (learningRate / (2 * len(X))) * np.sum(np.power(theta[:,1:theta.shape[1]], 2))\n",
    "    return np.sum(first - second) / len(X) + reg"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "请注意等式中的\"reg\" 项。还注意到另外的一个“学习率”参数。这是一种超参数，用来控制正则化项。现在我们需要添加正则化梯度函数："
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "如果我们要使用梯度下降法令这个代价函数最小化，因为我们未对${{\\theta }_{0}}$ 进行正则化，所以梯度下降算法将分两种情形：\n",
    "\\begin{align}\n",
    "  & Repeat\\text{ }until\\text{ }convergence\\text{ }\\!\\!\\{\\!\\!\\text{ } \\\\ \n",
    " & \\text{     }{{\\theta }_{0}}:={{\\theta }_{0}}-a\\frac{1}{m}\\sum\\limits_{i=1}^{m}{[{{h}_{\\theta }}\\left( {{x}^{(i)}} \\right)-{{y}^{(i)}}]x_{_{0}}^{(i)}} \\\\ \n",
    " & \\text{     }{{\\theta }_{j}}:={{\\theta }_{j}}-a\\frac{1}{m}\\sum\\limits_{i=1}^{m}{[{{h}_{\\theta }}\\left( {{x}^{(i)}} \\right)-{{y}^{(i)}}]x_{j}^{(i)}}+\\frac{\\lambda }{m}{{\\theta }_{j}} \\\\ \n",
    " & \\text{          }\\!\\!\\}\\!\\!\\text{ } \\\\ \n",
    " & Repeat \\\\ \n",
    "\\end{align}\n",
    "\n",
    "对上面的算法中 j=1,2,...,n 时的更新式子进行调整可得： \n",
    "${{\\theta }_{j}}:={{\\theta }_{j}}(1-a\\frac{\\lambda }{m})-a\\frac{1}{m}\\sum\\limits_{i=1}^{m}{({{h}_{\\theta }}\\left( {{x}^{(i)}} \\right)-{{y}^{(i)}})x_{j}^{(i)}}$\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def gradientReg(theta, X, y, learningRate):\n",
    "    theta = np.matrix(theta)\n",
    "    X = np.matrix(X)\n",
    "    y = np.matrix(y)\n",
    "    \n",
    "    parameters = int(theta.ravel().shape[1])\n",
    "    grad = np.zeros(parameters)\n",
    "    \n",
    "    error = sigmoid(X * theta.T) - y\n",
    "    \n",
    "    for i in range(parameters):\n",
    "        term = np.multiply(error, X[:,i])\n",
    "        \n",
    "        if (i == 0):\n",
    "            grad[i] = np.sum(term) / len(X)\n",
    "        else:\n",
    "            grad[i] = (np.sum(term) / len(X)) + ((learningRate / len(X)) * theta[:,i])\n",
    "    \n",
    "    return grad"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "就像在第一部分中做的一样，初始化变量。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# set X and y (remember from above that we moved the label to column 0)\n",
    "cols = data2.shape[1]\n",
    "X2 = data2.iloc[:,1:cols]\n",
    "y2 = data2.iloc[:,0:1]\n",
    "\n",
    "# convert to numpy arrays and initalize the parameter array theta\n",
    "X2 = np.array(X2.values)\n",
    "y2 = np.array(y2.values)\n",
    "theta2 = np.zeros(11)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "让我们初始学习率到一个合理值。，果有必要的话（即如果惩罚太强或不够强）,我们可以之后再折腾这个。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "learningRate = 1"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在，让我们尝试调用新的默认为0的theta的正则化函数，以确保计算工作正常。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.6931471805599454"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "costReg(theta2, X2, y2, learningRate)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([ 0.00847458,  0.01878809,  0.05034464,  0.01150133,  0.01835599,\n",
       "        0.00732393,  0.00819244,  0.03934862,  0.00223924,  0.01286005,\n",
       "        0.00309594])"
      ]
     },
     "execution_count": 35,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "gradientReg(theta2, X2, y2, learningRate)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "现在我们可以使用和第一部分相同的优化函数来计算优化后的结果。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 36,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(array([  1.22702519e-04,   7.19894617e-05,  -3.74156201e-04,\n",
       "         -1.44256427e-04,   2.93165088e-05,  -5.64160786e-05,\n",
       "         -1.02826485e-04,  -2.83150432e-04,   6.47297947e-07,\n",
       "         -1.99697568e-04,  -1.68479583e-05]), 96, 1)"
      ]
     },
     "execution_count": 36,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result2 = opt.fmin_tnc(func=costReg, x0=theta2, fprime=gradientReg, args=(X2, y2, learningRate))\n",
    "result2"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "最后，我们可以使用第1部分中的预测函数来查看我们的方案在训练数据上的准确度。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "accuracy = 77%\n"
     ]
    }
   ],
   "source": [
    "theta_min = np.matrix(result2[0])\n",
    "predictions = predict(theta_min, X2)\n",
    "correct = [1 if ((a == 1 and b == 1) or (a == 0 and b == 0)) else 0 for (a, b) in zip(predictions, y2)]\n",
    "accuracy = (sum(map(int, correct)) % len(correct))\n",
    "print ('accuracy = {0}%'.format(accuracy))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "虽然我们实现了这些算法，值得注意的是，我们还可以使用高级Python库像scikit-learn来解决这个问题。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,\n",
       "          intercept_scaling=1, max_iter=100, multi_class='ovr', n_jobs=1,\n",
       "          penalty='l2', random_state=None, solver='liblinear', tol=0.0001,\n",
       "          verbose=0, warm_start=False)"
      ]
     },
     "execution_count": 38,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from sklearn import linear_model#调用sklearn的线性回归包\n",
    "model = linear_model.LogisticRegression(penalty='l2', C=1.0)\n",
    "model.fit(X2, y2.ravel())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "0.66101694915254239"
      ]
     },
     "execution_count": 39,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "model.score(X2, y2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这个准确度和我们刚刚实现的差了好多，不过请记住这个结果可以使用默认参数下计算的结果。我们可能需要做一些参数的调整来获得和我们之前结果相同的精确度。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这就是练习2的全部！ 敬请期待下一个练习：多类图像分类。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
